#include "XTcp.h"
#include <windows.h>
#include "Logger.h"


XTcp::XTcp()
{
	static bool first = true;
	if (first)
	{
		first = false;
		//启动socket库
		WSADATA ws;
		WSAStartup(MAKEWORD(2, 2), &ws);
	}
	
}

XTcp::~XTcp()
{

}

int XTcp::createSocket()
{
	//创建socket
	this->sock = ::socket(AF_INET, SOCK_STREAM, 0);
	if (-1 == this->sock)
	{
		INFOLOGGER("create socket failed");
	}

	return this->sock;
}

bool XTcp::bind(unsigned short port)
{
	if (this->sock <= 0)
	{
		this->createSocket();
	}
	//定义数据结构
	sockaddr_in addr;
	addr.sin_family = AF_INET;//定义协议为tcp
	//本地字节序转网络字节序（网络字节序默认为大端，win默认为小段）
	addr.sin_port = htons(port);

	//绑定iP地址（多个网卡需要指定网卡）
	//1.绑定内网地址，只内部能访问该网络
	//2.绑定外网地址，只外部能访问该网络
	//3.所有皆可访问
	addr.sin_addr.s_addr = htonl(0);

	//绑定bind函数
	if (0 != ::bind(sock, (sockaddr*)&addr, sizeof(addr)))
	{
		INFOLOGGER("bind port %d faild!", port);
		return false;
	}
	INFOLOGGER("bind ip %s success!", inet_ntoa(addr.sin_addr));
	INFOLOGGER("bind port %d success!", port);
	//监听，调用监听告诉系统可以开始接受数据
	//参数：sock对象，backlog缓存大小
	listen(this->sock, 10);
	return true;
}

XTcp XTcp::accept()
{
	XTcp tcp;
	//数据结构，缓存读取的信息
	sockaddr_in caddr;
	int len = sizeof(struct sockaddr_in);
	//接受，读取用户连接信息（发送对象、发送地址）
	int client = ::accept(this->sock, (sockaddr*)&caddr, &len);//创建新的socket
	if (client <= 0)
	{
		return tcp; 
	}
	tcp.sock = client;
	char* ip = inet_ntoa(caddr.sin_addr);
	tcp.port = ntohs(caddr.sin_port);//网络字节序转本地字节序
	strcpy_s(tcp.ip, ip);
	INFOLOGGER("client socket %d", client);
	INFOLOGGER("client ip %s", tcp.ip);
	INFOLOGGER("client port %d", tcp.port);
	return tcp;
}

int XTcp::recv(char* buff, int bufsize)
{
	return ::recv(this->sock, buff, bufsize, 0);
}

int XTcp::send(const char* buff, int bufsize)
{
	int s = 0;
	while (s != bufsize)
	{
		int len = ::send(this->sock, buff + s, bufsize - s, 0);
		if (len <= 0)
			break;
		s += len;
	}
	return s;
}

void XTcp::close()
{
	if (this->sock <= 0)
		return;
	::closesocket(this->sock);
}

bool XTcp::isConnected()
{
	if (0 == this->port)
	{
		return false;
	}
	return true;
}

void XTcp::setSock(unsigned int sock)
{
	this->sock = sock;
}

unsigned int XTcp::getSock()
{
	return this->sock;
}
